#ifndef _sdl_world_h_
#define _sdl_world_h_

#include "sdl_graphic.h"
#include "sdl_prim.h"
#include "sdl_debug.h"
#include "sdl_mvector.h"
#include "sdl_layer.h"
#include <list>
#include <cmath>

namespace sdl_graphic {

    struct entity : public sdl_prim,
    depends<sdl_debug::debug> {
        sdl_ptr<mesh> body;
        matrix4x4f transform;
        entity(const std::string & n);
        void translate(const mvector3f & a);
    };

    /**
     * \brief Kamera ogólna
     * Tutaj implementujemy tylko "oko", które docelowo będzie "przyczepione" do pierwszej osoby i dlatego nie dajemy tutaj informacji o absolutnych osiach obrotu,
     */

    class camera : public sdl_layer {
        mvector3f position; ///<położenie
        mvector3f los; ///<line of sight
        mvector3f up; ///<do góry

        matrix4x4f transform;

    public:
        camera(const std::string & n);
        ///uaktualnienie macierzy transformacji
        virtual void update();
        ///obrót wokół linii optycznej
        void roll(const float & a);
        ///obrót wokół osi pionowej
        void yaw(const float & a);
        ///obrót wokół osi "w prawo" (wahanie góra/dół)
        void pitch(const float & a);
        ///poruszanie się zgodnie z los
        void move_forward(const float & a);
        void move_backward(const float & a);
        ///poruszanie się wzdłuż osi do góry
        void move_up(const float &a);
        void move_down(const float &a);
        void move_right(const float &a);
        void move_left(const float &a);
        void rotate(const mvector3f & n, const float & a);
        void translate(const mvector<float, 3 > & a);
        void reset();
        matrix4x4f get_transform();
        mvector3f get_up();
        mvector3f get_los();
        mvector3f get_right();
        mvector3f get_position();
    };

    class world : public sdl_prim,
    depends<sdl_debug::debug> {
        friend class renderer;
    public:
        std::list<sdl_ptr<entity> > population;
        sdl_ptr<camera> observer;
        //TODO: jakiś sdl_lighting czy coś
        //
        world(const std::string & n);
        ~world();
        void set_observer(const sdl_ptr<camera> & c);
        void push_back(const sdl_ptr<entity> & obj);
    };


}; //namespace sdl_graphic;


#endif //_sdl_world_h_

